

#include "typedef.h"
#include "lpc_data_type.h"
#include "Driver_I2c.h"
#include "i2c_module_interface.h"
#include "Config.h"

I2C_INSTANCE I2c_Instance[MAX_I2C_NUMB];
I2C_RXBUF	I2c_Drv_RxBuf[MAX_RXPACKAG_BUF];
int I2C_Config(LPC_INT8U ChanNum,LPC_INT8U RxBufNum,LPC_INT8U TOValue)
{
	LPC_INT8U i;

	if((ChanNum>=MAX_I2C_NUMB)||(RxBufNum>MAX_RXPACKAG_BUF))
	{
		return 1;
	}
	I2c_Instance[ChanNum].I2c_Addr = 0x00;
	I2c_Instance[ChanNum].EventMask = 0x00;
	I2c_Instance[ChanNum].IsStarted = 0;
	I2c_Instance[ChanNum].ClockRate = I2C_CLOCK_100K;
	I2c_Instance[ChanNum].CallBack_Fun = Null;    
	I2c_Instance[ChanNum].IsMonitor = 0;
	I2c_Instance[ChanNum].RxBuf_ReadPoint = 0;
	I2c_Instance[ChanNum].RxBuf_WritPoint = 0;
	if(ChanNum==0)
	{
		I2c_Instance[ChanNum].RxBuf_Number = RxBufNum;
		for(i=0;i<MAX_RXPACKAG_BUF;i++)
		{
			I2c_Instance[ChanNum].I2c_RxBuf[i] = &I2c_Drv_RxBuf[i];
			I2c_Instance[ChanNum].I2c_RxBuf[i]->DataValid = 0;
			I2c_Instance[ChanNum].I2c_RxBuf[i]->DataLen = 0;
		}
	}
	else
	{
		I2c_Instance[ChanNum].RxBuf_Number = 0;
		for(i=0;i<MAX_RXPACKAG_BUF;i++)
		{
			I2c_Instance[ChanNum].I2c_RxBuf[i] = Null;
		}
	}
	I2c_Instance[ChanNum].IsReady = 1;

	return 0;
}


int I2C_RegClient(LPC_INT8U ChanNum,LPC_INT8U EventMask,void * I2C_CallBack,LPC_INT8U AdrLen,LPC_INT8U * AdrList)
{
	LPC_STATUS rtnStatus;
	LPC_INT8U len,addr;

	if((ChanNum>=MAX_I2C_NUMB) || (AdrLen>MAX_SLAVADDR_NUM) )        // || (I2C_CallBack==Null) || (AdrList==Null))
	{
		return 1;
	}
	if(I2c_Instance[ChanNum].IsReady == 0)
	{
		return 1;
	}

	I2c_Instance[ChanNum].EventMask = EventMask;
	I2c_Instance[ChanNum].CallBack_Fun = (void (*)())I2C_CallBack;

	for(len=0;len<AdrLen;len++)
	{
		addr = AdrList[len];
		I2c_Instance[ChanNum].I2c_Addr = addr;
	}


	rtnStatus = I2cInit(ChanNum,addr,I2c_Instance[ChanNum].ClockRate);
	if(rtnStatus==LPC_SUCCESS)
	{
		I2c_Instance[ChanNum].IsStarted = 1;            
	}
	else
	{
		I2c_Instance[ChanNum].IsStarted = 0;        
	}

	return rtnStatus;

}

int I2C_UnregClient(LPC_INT8U ChanNum,LPC_INT8U AdrLen,LPC_INT8U * AdrList)
{
	LPC_INT8U addr;

	if((ChanNum>=MAX_I2C_NUMB) || (AdrList==Null)||(AdrLen>MAX_SLAVADDR_NUM))
	{
		return 1;
	}


	addr = AdrList[0];
	if(addr==I2c_Instance[ChanNum].I2c_Addr)
	{
		I2c_Instance[ChanNum].I2c_Addr = 0x00;
		I2c_Instance[ChanNum].EventMask = 0x00;
		I2c_Instance[ChanNum].CallBack_Fun = Null;
		I2c_Instance[ChanNum].IsStarted = 0;    
		return 0;
	}
	else
	{
		return 1;
	}

}

uint8 I2C_GetBusEvent(LPC_INT8U ChanNum)
{
	uint8 eventState = 0x00;
	switch (I2c_IntrState_Get(ChanNum))
	{
	case I2C_INTRSTA_NAUG:
		eventState = 0x00;
		break;
	case I2C_INTRMSD_CMPT:
	case I2C_INTRSSD_CMPT :
		eventState = eventState | EVENT_TXOK_MASK;
		break;
	case I2C_INTRMSD_ALST:
		eventState = eventState | EVENT_TXBY_MASK;
		break;
	case I2C_INTRMSD_NACK:
		eventState = eventState | EVENT_TXNA_MASK;
		break;
	case I2C_INTRMSD_TOUT:
		eventState = eventState | EVENT_TXBE_MASK;
		break;
	case I2C_INTRSRV_CMPT:
	case I2C_INTRMRV_CMPT:
		eventState = eventState | EVENT_RXOK_MASK;
		break;
	case I2C_INTRMRV_ALST:
		eventState = eventState | EVENT_RXBY_MASK;
		break;
	case I2C_INTRMRV_NACK:
		eventState = eventState | EVENT_RXNA_MASK;
		break;
	case I2C_INTRSRV_MOVR:
	case I2C_INTRMRV_TOUT:
		eventState = eventState | EVENT_RXBE_MASK;
		break;

	default : break;
	}

	return eventState;
}

int I2C_TxData(LPC_INT8U ChanNum,LPC_INT8U DataLen,void * DataBuf)
{
	int nRet = 0;
	uint32 nCount = 0;
	const static uint32 MAX_VALUE = MS_COUNT * 10;
	
	nRet = I2C_TxDataEx(ChanNum, DataLen, DataBuf);

	while(nRet == LPC_SUCCESS && nCount++ < MAX_VALUE)
	{
		if(LPC_SUCCESS == I2c_Module_IsIdle(ChanNum))
		{
			uint8 busEvent = I2C_GetBusEvent(ChanNum);
			if((busEvent & EVENT_TXOK_MASK) || (busEvent & EVENT_RXOK_MASK))
			{
				return LPC_SUCCESS;
			}
			break;
		}
	}
	
	return LPC_FAILURE;
}

int I2C_TxDataEx(LPC_INT8U ChanNum,LPC_INT8U DataLen,void * DataBuf)
{
	int nRet = 0;
	
	if((ChanNum>=MAX_I2C_NUMB) || (DataLen>MAX_PACKG_LENGTH)  || (DataBuf==Null))
	{
		return LPC_FAILURE;
	}
	
	if(I2c_Module_IsIdle(ChanNum) != LPC_SUCCESS)
	{
		return LPC_FAILURE;
	}
	
	if(I2c_Instance[ChanNum].IsStarted != 1)
	{
		return LPC_FAILURE;
	}

	if(ChanNum==0)
	{
		nRet = I2C0_WriteNByte((LPC_INT8U *) DataBuf, DataLen);
	}
	else
	{
		nRet = I2C1_WriteNByte((LPC_INT8U *) DataBuf, DataLen);
	}

	return nRet;
}

int I2C_RxData(LPC_INT8U ChanNum,LPC_INT8U MaxLen,void * DataBuf)
{
	LPC_BOOL empty;
	LPC_INT8U tempLen;

	if((ChanNum>=MAX_I2C_NUMB) || (MaxLen>MAX_PACKG_LENGTH) || (DataBuf==Null))
	{
		return 1;    //parameter error
	}

	tempLen = I2c_RxBuf_Read(ChanNum, MaxLen, DataBuf);
	empty = I2c_RxBuf_IsEmpty(ChanNum);
	if(empty == FALSE)
	{
		I2c_CallBack_Handle(ChanNum,EVENT_RXOK_MASK);
	}

	return tempLen;
}


int I2C_GetStatus(LPC_INT8U ChanNum,LPC_INT8U * RxBufStatus,LPC_INT8U * TxBufStatus,LPC_INT8U * EventStatus)
{    
	LPC_INT8U rBufState;
	LPC_INT8U tBufstate,tempState;
	LPC_INT8U eventState;

	if((ChanNum>=MAX_I2C_NUMB) || (RxBufStatus ==Null) || (TxBufStatus==Null) || (EventStatus==Null))
	{
		return 1;    //parameter error
	}

	rBufState = 0; tBufstate = 0; eventState = 0;
	if((I2c_RxBuf_IsFull(ChanNum))==TRUE)
	{
		rBufState = rBufState|STATUS_BUF_FULL;
	}
	else if(I2c_RxBuf_IsEmpty(ChanNum)==TRUE)
	{
		rBufState = rBufState|STATUS_BUF_EMPT;
	}
	*RxBufStatus = rBufState;

	tempState = I2c_WorkState_Get(ChanNum);
	switch (tempState)
	{
	case I2C_WORKSTA_IDLE:
		tBufstate = tBufstate | STATUS_BUF_EMPT;
		break;
	case I2C_WORKSTA_MSND:
	case I2C_WORKSTA_RSND:
	case I2C_WORKSTA_MRCV:
	case I2C_WORKSTA_SRCV:
	case I2C_WORKSTA_SSND:
	case I2C_WORKSTA_WAIT:
	case I2C_WORKSTA_ERRO:
		tBufstate = tBufstate | STATUS_BUF_FULL;
		break;

	default : break;
	}
	*TxBufStatus = tBufstate;

	eventState = I2C_GetBusEvent(ChanNum);

	*EventStatus = eventState;

	return 0;        //success get
}


LPC_INT8U I2c_RxBuf_Read(LPC_INT8U deviceId,LPC_INT8U maxLen,void * data)
{
	LPC_INT8U *bufPointer;
	LPC_INT8U *pData;
	LPC_INT8U readPoint;
	LPC_INT8U tempLen,i;

	if ((deviceId>=MAX_I2C_NUMB)||(maxLen>MAX_PACKG_LENGTH)||(data==Null))
	{
		return 1;
	}
	pData = (LPC_INT8U *)data;
	if(I2c_Instance[deviceId].RxBuf_Number<1)
	{
		tempLen = I2c_RecvNumb_Get(deviceId);
		tempLen = (maxLen>tempLen)?tempLen:maxLen;
		bufPointer = I2c_RecvBuf_Get(deviceId);

		for(i=0;i<tempLen;i++)
		{
			pData[i] = bufPointer[i];
		}
		return tempLen;
	}

	if(I2c_RxBuf_IsEmpty(deviceId) == TRUE)
	{
		return 0;
	}
	readPoint = I2c_Instance[deviceId].RxBuf_ReadPoint;		

	if((I2c_Instance[deviceId].I2c_RxBuf[readPoint]->DataLen)>=maxLen)
	{
		tempLen = maxLen;
	}
	else
	{
		tempLen = I2c_Instance[deviceId].I2c_RxBuf[readPoint]->DataLen;
	}
	for(i=0;i<tempLen;i++)
	{
		pData[i] = I2c_Instance[deviceId].I2c_RxBuf[readPoint]->DataBuf[i];
	}
	I2c_Instance[deviceId].I2c_RxBuf[readPoint]->DataLen = 0;
	I2c_Instance[deviceId].I2c_RxBuf[readPoint]->DataValid = 0;

	I2c_Instance[deviceId].RxBuf_ReadPoint++;
	if(I2c_Instance[deviceId].RxBuf_ReadPoint>=I2c_Instance[deviceId].RxBuf_Number)
	{
		I2c_Instance[deviceId].RxBuf_ReadPoint = 0;
	}

	return tempLen;
}

LPC_BOOL I2c_RxBuf_IsEmpty(LPC_INT8U deviceId)
{
	LPC_INT8U readPoint,writPoint;

	if (deviceId>=MAX_I2C_NUMB)
	{
		return TRUE;
	}

	readPoint = I2c_Instance[deviceId].RxBuf_ReadPoint;
	writPoint = I2c_Instance[deviceId].RxBuf_WritPoint;
	if(readPoint == writPoint)
	{
		return TRUE;
	}
	else{
		return FALSE;
	}
}

LPC_BOOL I2c_RxBuf_IsFull(LPC_INT8U deviceId)
{
	LPC_INT8U readPoint,writPoint,bufNum;

	if (deviceId>=MAX_I2C_NUMB)
	{
		return FALSE;
	}

	bufNum = I2c_Instance[deviceId].RxBuf_Number;
	readPoint = I2c_Instance[deviceId].RxBuf_ReadPoint;
	writPoint = I2c_Instance[deviceId].RxBuf_WritPoint;
	writPoint = writPoint+1;
	if(writPoint>=bufNum)
	{
		writPoint = 0;
	}
	if(readPoint==writPoint)
	{
		return TRUE;
	}
	else{
		return FALSE;
	}
}

void I2c_CallBack_Handle(LPC_INT8U deviceId,LPC_INT8U eventInd)
{
	I2c_Instance[deviceId].CallBack_Fun(deviceId,eventInd);
}

int  I2c_Device_Read(LPC_INT8U ChanNum,LPC_INT8U *SendData,LPC_INT8U SendLen,LPC_INT8U *RecvData,LPC_INT8U RecvLen)
{
	LPC_INT8U tempSAddr;
	LPC_INT8U state;
	int tempLen;

	if((ChanNum>=MAX_I2C_NUMB) || (SendLen<1) || (RecvLen<1) || (SendData==Null) || (RecvData==Null))
	{
		return 0;
	}

	tempSAddr = SendData[0];
	if(SendLen>1)
	{
		SendData[0] = tempSAddr&0xfe;                // force to write
		if(LPC_SUCCESS != I2C_TxData(ChanNum, SendLen, SendData))
		{
			return 0;
		}
	}

	SendData[0] = tempSAddr|0x01;                //force to read
	if(LPC_SUCCESS != I2C_TxData(ChanNum, RecvLen, SendData))    //RecvLen include the slaveAddr;
	{
		return 0;
	}

	state = I2c_IntrState_Get(ChanNum);
	if((state==I2C_INTRMRV_CMPT)||(state==I2C_INTRMRV_NACK))
	{
		tempLen = I2c_RxBuf_Read(ChanNum,RecvLen, RecvData);
		return tempLen;
	}
	else
	{
		return 0;
	}

}

LPC_STATUS I2c_RxHBuf_Read(LPC_INT8U deviceId)
{    
	LPC_INT8U *bufPointer;        
	LPC_INT8U i,length;
	LPC_INT8U wrtPoint;

	if (deviceId>=MAX_I2C_NUMB) 
	{
		return LPC_PARA_ERROR;
	}
	if(I2c_Instance[deviceId].RxBuf_Number<1)
	{
		return LPC_SUCCESS;
	}

	length = I2c_RecvNumb_Get(deviceId);	
	if(length<MIN_PACKG_LENGTH)
	{
		return LPC_FAILURE;
	}
	wrtPoint = I2c_Instance[deviceId].RxBuf_WritPoint;
	bufPointer = I2c_RecvBuf_Get(deviceId);

	for(i=0;i<length;i++)
	{
		I2c_Instance[deviceId].I2c_RxBuf[wrtPoint]->DataBuf[i] = bufPointer[i] ;
	}
	I2c_Instance[deviceId].I2c_RxBuf[wrtPoint]->DataLen = length;
	I2c_Instance[deviceId].I2c_RxBuf[wrtPoint]->DataValid = 1;

	I2c_Instance[deviceId].RxBuf_WritPoint++;
	if(I2c_Instance[deviceId].RxBuf_WritPoint>=I2c_Instance[deviceId].RxBuf_Number)
	{
		I2c_Instance[deviceId].RxBuf_WritPoint = 0;
	}

	return LPC_SUCCESS;
}


void I2c_InterruptHandler(LPC_INT8U ChanNum)
{
	LPC_INT8U eventMask,eventState;    
	LPC_STATUS rtnStatus;

	if(ChanNum>=MAX_I2C_NUMB)
	{
		return;
	}

	eventState = I2C_GetBusEvent(ChanNum);
	eventMask = I2c_Instance[ChanNum].EventMask;

	rtnStatus = LPC_SUCCESS;    
	if((eventState&EVENT_RXOK_MASK) != 0)
	{                
		rtnStatus = I2c_RxHBuf_Read(ChanNum);
	}
	eventState = eventState & eventMask;
	if((rtnStatus==LPC_SUCCESS) && (eventState!=0))
	{
		I2c_CallBack_Handle(ChanNum,eventState);
	}

	return;
}


